/**********************************************************************\
 © COPYRIGHT 2006 Corporation for National Research Initiatives (CNRI);
                        All rights reserved.
               
        The HANDLE.NET software is made available subject to the
         Handle System Public License, which may be obtained at
         http://hdl.handle.net/4263537/5030 or hdl:4263537/5030
\**********************************************************************/

/**********************************************************************\
Redirects to a mirror based on a browser cookie.  If there is no cookie
first mirror is used.
\***********************************************************************/

package net.handle.apps.servlet_proxy.handlers;

import javax.servlet.*;
import javax.servlet.http.*;
import net.handle.hdllib.*;
import java.util.*;
import java.io.IOException;
import net.handle.apps.servlet_proxy.*;

public class MirrorUrls implements TypeHandler {
  private static final byte MIRROR_URLS_TYPE[] = Util.encodeString("MIRROR_URLS");
  private static final byte MIRROR_URLS_REF_TYPE[] = Util.encodeString("MIRROR_URLS_REF");
  public static final String COOKIE = "preferred_country";
  
  /** 
  * Return true iff this TypeHandler can send a redirect to the client
  * based on the given set of HandleValues.
  */
  public boolean canRedirect(HandleValue values[]) {
    if(values==null) return false;
    for(int i=values.length-1; i>=0; i--) {
      if(values[i].hasType(MIRROR_URLS_TYPE))
        return true;
      if(values[i].hasType(MIRROR_URLS_REF_TYPE))
        return true;
    }
    return false;
  }

  /** 
    * Return true iff this TypeHandler can and should be used to format the 
    * data from the given HandleValue for a human client.
    */
  public boolean canFormat(HandleValue value) {
    return false;
  }
  
  public String toHTML(String handle, HandleValue value){
    return value.getDataAsString();
  }
  
  private String getCountry(HttpServletRequest req) {
    Cookie cookies[] = req.getCookies();
    if (cookies == null) return null;
    for (int i=0; i<cookies.length; i++){
      if (cookies[i].getName().equals(COOKIE)){
        return cookies[i].getValue();
      }
    } 
    return null;
  }

  public boolean doRedirect(HttpServletRequest req, 
                            HttpServletResponse resp, HttpParams params,
                            String handle, HandleValue vals[])
    throws IOException
  {
    if(vals==null) return false;
    
    // if there is a MIRROR_URLS value, use that...
    HandleValue val;
    for(int i=0; i<vals.length; i++) {
      val = vals[i];
      if(val.hasType(MIRROR_URLS_TYPE)) {
        return doMirrorUrls(req, resp, params, handle, val);
      }
    }
    
    // ...otherwise, look for a MIRROR_URLS_REF value
    for(int i=0; i<vals.length; i++) {
      val = vals[i];
      if(val.hasType(MIRROR_URLS_REF_TYPE)) {
        return doMirrorUrlsRef(req, resp, params, handle, val);
      }
    }
    return false; // didn't redirect for some reason
  }
  
  
  
  /**
   * MIRROR_URLS_REF values contain a suffix(ie the mirrored document) and 
   * a handle+index to a MIRROR_URLS list to append the suffix to.
   *
   * suffix is all chars up to space(not \t or \n).  index:handle is the rest
   * of the value.  e.g.:
   * 
   * /mydir/foo.html 1:10.1045/mirrorsites
   **/
  boolean doMirrorUrlsRef(HttpServletRequest req, 
                          HttpServletResponse resp, HttpParams params,
                          String handle, HandleValue val)
    throws IOException
  {
    try {
      String data = val.getDataAsString();
      int i = data.indexOf(' ');
      String suffix = data.substring(0, i).trim();
      String ref = data.substring(i).trim();
      i = ref.indexOf(':');
      int index = Integer.parseInt(ref.substring(0, i));
      String hdl = ref.substring(i+1);
      HandleValue vals[] = HDLProxy.resolver.resolveHandle(hdl, null, new int[]{index});
      String mirror = getMirror(req, vals[0]);
      if (mirror == null) return false;
      String append = params.getParameter("urlappend");
      if (append == null) append = "";
      resp.sendRedirect(mirror+suffix+append);
      return true;
    }
    catch (Exception e){
      System.out.println("Error in doMirrorUrlsRef for "+handle+": "+e); 
      return false;
    }
     
  }

  boolean doMirrorUrls(HttpServletRequest req, 
                       HttpServletResponse resp, HttpParams params,
                       String handle, HandleValue val)
     throws IOException
  {
    String url = getMirror(req, val);
    if (url == null) return false;
    String suffix = params.getParameter("urlappend");
    if (suffix == null) suffix = "";
    resp.sendRedirect(url+suffix);
    return true;
  }

  String getMirror(HttpServletRequest req, HandleValue val){
    String preferredCountry = getCountry(req);
    StringTokenizer tok = new StringTokenizer(val.getDataAsString());
    String first = null;
    while (tok.hasMoreElements()){
      String country = (String)tok.nextElement();
      String url = (String)tok.nextElement();
      // System.err.println("COUNTRY: "+country+" =? "+preferredCountry);
      if (first == null) first = url;
      if (preferredCountry==null || preferredCountry.equals(country)){
        return url;
      }
    }
    return first;
  }
}
